const crypto = require("crypto");
const token = {

    /**
     * 创建token
     * @param obj  辅助监测用户id {Id:'用户id'}
     * @param timeout token有效时间
     * @returns {string}
     */
    createToken: function (obj, timeout) {
        let obj2 = {
            data: obj,//payload
            created: parseInt(Date.now() / 1000),//token生成的时间的，单位秒
            exp: parseInt(timeout) || 10//token有效期
        };
        //payload信息
        let base64Str = Buffer.from(JSON.stringify(obj2), "utf8").toString("base64");

        //添加签名，防篡改
        let secret = "public.youdo.com";
        let hash = crypto.createHmac('sha256', secret);
        hash.update(base64Str);
        let signature = hash.digest('base64');


        return base64Str + "." + signature;
    },

    /**
     * 解析token
     * @param token 待检测token数据
     * @returns {boolean|{payload, signature: (*|string), checkSignature: PromiseLike<ArrayBuffer>}}
     */
    decodeToken: function (token) {

        let decArr = token.split(".");
        if (decArr.length < 2) {
            //token不合法
            return false;
        }

        let payload = {};
        //将payload json字符串 解析为对象
        try {
            payload = JSON.parse(Buffer.from(decArr[0], "base64").toString("utf8"));
        } catch (e) {
            return false;
        }

        //检验签名
        let secret = "public.youdo.com";
        let hash = crypto.createHmac('sha256', secret);
        hash.update(decArr[0]);
        let checkSignature = hash.digest('base64');

        return {
            payload: payload,
            signature: decArr[1],
            checkSignature: checkSignature
        }
    },

    /**
     * 检查token是否正确
     * @param token 待检测token数据
     * @param userId 当前登录者Id
     * @returns {boolean}
     */
    checkToken: function (token, userId) {
        token = token === undefined ? "" : token;
        let resDecode = this.decodeToken(token);
        if (!resDecode) {
            return false;
        }
        //是否过期
        let expState = (parseInt(Date.now() / 1000) - parseInt(resDecode.payload.created)) > parseInt(resDecode.payload.exp) ? false : true;

        if (resDecode.signature === resDecode.checkSignature && expState && resDecode.payload.data.Id === userId) {
            return true;
        }
        return false;
    }

};

module.exports = token;
